home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / TouchMe 1.2□ / touchMe 1.2 Folder / touchMe source codes / CW11 PP source / source / Common Lib / UDragDropSuit.cp < prev    next >
Encoding:
Text File  |  1997-04-25  |  8.3 KB  |  277 lines  |  [TEXT/CWIE]

  1. // ==================================================
  2. //    UDragDropSuit.cp
  3. //    Copyright (C) 1996-1997 Mizutori Tetsuya
  4. //    November 22, 1996; February 6, 1997.
  5. // ==================================================
  6. //    All documents are pretty-printed in 10-point Geneva font.
  7.  
  8.  
  9. #include <LDragAndDrop.h>
  10.  
  11. #include "UDragDropSuit.h"
  12.  
  13.  
  14. // === Static Class Variables ===
  15. RgnHandle        UDragDropSuit::sDragRegion    = ::NewRgn();
  16.  
  17.  
  18. // --------------------------------------------------
  19. //        • DragText
  20. // --------------------------------------------------
  21. //    Drag the selected text in the given document.
  22. //    Author:    Rob Johnston @ Apple Computer, Inc.
  23. //    Date:        Friday, September 10, 1993
  24. //    Modifier:    Mizutori Tetsuya, November 22, 1996
  25.  
  26. Boolean
  27. UDragDropSuit::DragText(
  28.     const EventRecord &    theEvent,
  29.     RgnHandle            inHiliteRgn,
  30.     unsigned char *        textP,
  31.     long &            textLen,
  32.     Boolean &            wasDroppedInTrash )
  33. {
  34.     if ( ! LDropArea::DragAndDropIsPresent() ) return false;
  35.  
  36.     Boolean        result = true;
  37.  
  38.     wasDroppedInTrash = false;
  39.  
  40.     //    Wait for the mouse to move to the mouse button to be released. If the mouse button was
  41.     //    released before the mouse moves, return false. Returing false from DragText means that
  42.     //    a drag operation did not occur.
  43.  
  44.     if ( ! ::WaitMouseMoved(theEvent.where) ) return false;
  45.  
  46.     //    Prepare a drag handler.
  47.     DragReference    theDrag;
  48.     ::NewDrag( &theDrag );
  49.  
  50.     //    For purposes of demonstration, we insert the 'TEXT' data and promise 'styl'
  51.     //    data. If a receiver requests 'TEXT', the Drag Manager will give them the text
  52.     //    without needing us to intervene. If a receiver requests 'styl', the Drag Manager
  53.     //    will call our MySendDataProc to provide the data at drop time. The MySendDataProc
  54.     //    is specified by calling SetDragSendProc.
  55.     ::AddDragItemFlavor( theDrag, 1, 'TEXT', textP, textLen, 0L );
  56.  
  57.     //::SetDragSendProc( theDrag, (DragSendDataUPP) sDragSendDataProc, (void *) this );
  58.  
  59.     //::SetDragDrawingProc( theDrag, (DragDrawingUPP) sDragDrawingProc, (void *) this );
  60.  
  61.     if ( ! MyTrackDrag( theDrag, theEvent, inHiliteRgn ) ) goto bail;
  62.  
  63.     //    Check to see if the drop occurred in the Finder's Trash. If the drop occurred
  64.     //    in the Finder's Trash and a copy operation wasn't specified, delete the
  65.     //    source selection. Note that we can continute to get the attributes, drop location
  66.     //    modifiers, etc. of the drag until we dispose of it using DisposeDrag.
  67.     DragAttributes        attributes;
  68.     ::GetDragAttributes( theDrag, &attributes );
  69.  
  70. #ifdef COMMENT
  71.     if ( (attributes & dragInsideSenderWindow) == 0 ) {
  72.         result = false;
  73.     } else
  74. #endif // COMMENT
  75.  
  76.     if ( (attributes & dragInsideSenderApplication) == 0 ) {
  77.  
  78.         AEDesc    dropLocation;
  79.         ::GetDropLocation( theDrag, &dropLocation );
  80.  
  81.         short        mouseDownModifiers, mouseUpModifiers;
  82.         ::GetDragModifiers( theDrag, 0L, &mouseDownModifiers, &mouseUpModifiers );
  83.  
  84.         short    copyText = (mouseDownModifiers | mouseUpModifiers) & optionKey;
  85.         if ( copyText == 0 && DropLocationIsFinderTrash( dropLocation ) ) {
  86.             wasDroppedInTrash = true;
  87.         }
  88.  
  89.         ::AEDisposeDesc( &dropLocation );
  90.     }
  91.  
  92. bail:
  93.     //    Dispose of the drag.
  94.     if ( theDrag != NULL ) ::DisposeDrag( theDrag );
  95.  
  96.     return result;
  97. }
  98.  
  99.  
  100. // --------------------------------------------------
  101. //        • MyTrackDrag
  102. // --------------------------------------------------
  103. //    Do my TrackDrag, respecting to which the mouse position is in the original drag region.
  104.  
  105. Boolean
  106. UDragDropSuit::MyTrackDrag(
  107.     DragReference        inDrag,
  108.     const EventRecord &    inMacEvent,
  109.     RgnHandle            inDragRegion )
  110. {
  111.     //    Copy the hilite region into dragRegion and offset it into global coordinates.
  112.     //    CAUTION:  you must ::SetPort() before getting ::LocalToGlobal().
  113.     RgnHandle        dragRegion = ::NewRgn();
  114.     ::CopyRgn( inDragRegion, dragRegion );
  115.  
  116.     Point            theLocalOrigin;
  117.     ::SetPt( &theLocalOrigin, 0, 0 );
  118.     ::LocalToGlobal( &theLocalOrigin );
  119.     ::OffsetRgn( dragRegion, theLocalOrigin.h, theLocalOrigin.v );
  120.  
  121.     // Set my original drag region.
  122.     ::CopyRgn( dragRegion, sDragRegion );
  123.  
  124.     //    Set the item's bounding rectangle in global coordinates.
  125.     ::SetDragItemBounds( inDrag, 1, &(**dragRegion).rgnBBox );
  126.  
  127.     //    Prepare the drag region.
  128.     RgnHandle    tempRgn = ::NewRgn();
  129.     ::CopyRgn( dragRegion, tempRgn );
  130.     ::InsetRgn( tempRgn, 1, 1 );
  131.     ::DiffRgn( dragRegion, tempRgn, dragRegion );
  132.     ::DisposeRgn( tempRgn );
  133.  
  134.     //    Drag the text. TrackDrag will return userCanceledErr if the drop zoomed-back
  135.     //    for any reason.
  136.     OSErr    err;
  137.     err = ::TrackDrag( inDrag, &inMacEvent, dragRegion );
  138.  
  139.     ::DisposeRgn( dragRegion );
  140.  
  141.     ::SetEmptyRgn( sDragRegion );
  142.  
  143.     return ( err == noErr || err == userCanceledErr );
  144. }
  145.  
  146.  
  147. // --------------------------------------------------
  148. //        • DropLocationIsFinderTrash
  149. // --------------------------------------------------
  150. //    Returns true if the given dropLocation AEDesc is a descriptor of the Finder's Trash.
  151.  //    Author:    Rob Johnston @ Apple Computer, Inc.
  152. //    Date:        Friday, September 10, 1993
  153. //    Modifier:    Mizutori Tetsuya, November 22, 1996
  154.  
  155. Boolean
  156. UDragDropSuit::DropLocationIsFinderTrash(
  157.     AEDesc &        dropLocation )
  158.  
  159. {
  160.     //    Coerce the dropLocation descriptor to an FSSpec. If there's no dropLocation or
  161.     //    it can't be coerced into an FSSpec, then it couldn't have been the Trash.
  162.     if ( dropLocation.descriptorType == typeNull ) return false;
  163.  
  164.     AEDesc        dropSpec;
  165.     if ( ::AECoerceDesc( &dropLocation, typeFSS, &dropSpec ) != noErr ) return false;
  166.  
  167.     ::HLock( dropSpec.dataHandle );
  168.     FSSpec *        theSpec = (FSSpec *) *dropSpec.dataHandle;
  169.  
  170.     //    Get the directory ID of the given dropLocation object.
  171.  
  172.     CInfoPBRec    thePB;
  173.     thePB.dirInfo.ioCompletion    = 0L;
  174.     thePB.dirInfo.ioNamePtr    = (StringPtr) &theSpec->name;
  175.     thePB.dirInfo.ioVRefNum    = theSpec->vRefNum;
  176.     thePB.dirInfo.ioFDirIndex    = 0;
  177.     thePB.dirInfo.ioDrDirID    = theSpec->parID;
  178.  
  179.     OSErr    err = ::PBGetCatInfoSync( &thePB );
  180.  
  181.     ::HUnlock( dropSpec.dataHandle );
  182.     ::AEDisposeDesc( &dropSpec );
  183.  
  184.     if ( err != noErr ) return false;
  185.  
  186.     //    If the result is not a directory, it must not be the Trash.
  187.     if ((thePB.dirInfo.ioFlAttrib & (1 << 4)) == 0 ) return false;
  188.  
  189.     //    Get information about the Trash folder.
  190.     short            trashVRefNum;
  191.     long            trashDirID;
  192.     ::FindFolder( theSpec->vRefNum, kTrashFolderType, kCreateFolder, &trashVRefNum, &trashDirID );
  193.  
  194.     //    If the directory ID of the dropLocation object is the same as the directory ID
  195.     //    returned by FindFolder, then the drop must have occurred into the Trash.
  196.     if ( thePB.dirInfo.ioDrDirID == trashDirID ) return true;
  197.  
  198.     return false;
  199. }
  200.  
  201.  
  202. // --------------------------------------------------
  203. //        • InDragRegion
  204. // --------------------------------------------------
  205. //    Determine which the current mouse position is in the initial drag region.
  206.  
  207. Boolean
  208. UDragDropSuit::InDragRegion(
  209.     DragReference    inDragRef )
  210. {
  211.     OSErr    err;
  212.     Boolean    result = false;
  213.  
  214.     Point        theMouseOrg;
  215.     Point        theMousePos;
  216.     err = ::GetDragMouse( inDragRef, &theMousePos, NULL );
  217.     err = ::GetDragOrigin( inDragRef, &theMouseOrg );
  218.  
  219.     result = ::PtInRgn( theMousePos, sDragRegion );
  220.  
  221.     return result;
  222. }
  223.  
  224.  
  225. // --------------------------------------------------
  226. //        • ZoomBackBounds
  227. // --------------------------------------------------
  228. //    Provide zooming rects from destination to source when the drag was failed.
  229.  
  230. void
  231. UDragDropSuit::ZoomBackBounds(
  232.     DragReference    inDragRef,
  233.     ItemReference    inItemRef )
  234. {
  235.     OSErr    err;
  236.  
  237.     Point        theMouseOrg;
  238.     Point        theMousePos;
  239.     Point        thePinnedMousePos;
  240.     err = ::GetDragMouse( inDragRef, &theMousePos, &thePinnedMousePos );
  241.     err = ::GetDragOrigin( inDragRef, &theMouseOrg );
  242.  
  243.     Point        theDelta = theMouseOrg;
  244.     ::SubPt( theMousePos, &theDelta );
  245.  
  246.     if ( ::EmptyRgn( sDragRegion ) ) {
  247.  
  248.         // Retrieve the icon bounds which was set by the Finder.
  249.         // But we can not get the CORRECT bounds for it, the reason why I do not know.
  250.         Rect    theBoundRect;
  251.         ::GetDragItemBounds( inDragRef, inItemRef, &theBoundRect );
  252.     //    ::OffsetRect( &theBoundRect, thePinnedMousePos.h, thePinnedMousePos.v );
  253.         ::OffsetRect( &theBoundRect, - theBoundRect.left, - theBoundRect.top );
  254.  
  255.         Rect    fromRect = theBoundRect;
  256.         Rect    toRect = theBoundRect;
  257. //        ::OffsetRect( &toRect, theDelta.h, theDelta.v );
  258.         ::OffsetRect( &fromRect, theMousePos.h, theMousePos.v );
  259.         ::OffsetRect( &toRect, theMouseOrg.h, theMouseOrg.v );
  260.  
  261.         ::ZoomRects( &fromRect, &toRect, 12, zoomDecelerate );
  262.  
  263.     } else {
  264.  
  265.         RgnHandle    theDropRgn = ::NewRgn();
  266.         ::CopyRgn( sDragRegion, theDropRgn );
  267.         ::OffsetRgn( theDropRgn, - theDelta.h, - theDelta.v );
  268.  
  269.         ::ZoomRegion( theDropRgn, theDelta, 12, zoomDecelerate );
  270.  
  271.         ::DisposeRgn( theDropRgn );
  272.     }
  273. }
  274.  
  275.  
  276. // end of program
  277.